﻿using System;
using System.Collections.Generic;
using OpenTK.Graphics.OpenGL4;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;

namespace Painter3D.RenderSys
{
    /// <summary>
    /// 立方体贴图
    /// </summary>
    class TextureBox
    {
        private int Handle;
        public TextureMagFilter MagFilter
        {
            set
            {
                GL.BindTexture(TextureTarget.TextureCubeMap, Handle);
                GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureMagFilter, (int)MagFilter);
                MagFilter = value;
            }
            get
            {
                return MagFilter;
            }
        }
        public TextureMinFilter MinFilter
        {
            set
            {
                GL.BindTexture(TextureTarget.TextureCubeMap, Handle);
                GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureMagFilter, (int)MinFilter);
                MinFilter = value;
            }
            get
            {
                return MinFilter;
            }
        }
        public TextureWrapMode WrapMode
        {
            set
            {
                GL.BindTexture(TextureTarget.TextureCubeMap, Handle);
                GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureWrapR, (int)WrapMode);
                GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureWrapS, (int)WrapMode);
                GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureWrapT, (int)WrapMode);
                WrapMode = value;
            }
            get
            {
                return WrapMode;
            }
        }
        /// <summary>
        /// 创建立方体贴图
        /// </summary>
        /// <param name="paths">六个面的图片路径,[右,左,上,下,后,前]</param>
        /// <param name="flipVertical">垂直反转图片</param>
        /// <param name="flipHorizontal">水平反转图片</param>
        public TextureBox(string[] paths, bool flipVertical = true, bool flipHorizontal = false)
        {
            if (paths.Length != 6)
                throw new Exception("立方体贴图需要给与六个面的图片路径");
            Handle = GL.GenTexture();

            GL.ActiveTexture(TextureUnit.Texture0);
            GL.BindTexture(TextureTarget.TextureCubeMap, Handle);

            GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
            GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
            GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureWrapR, (int)TextureWrapMode.ClampToEdge);
            GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge);
            GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);

            for (int i = 0; i < 6; i++)
            {
                using (Image<Rgba32> image = Image.Load<Rgba32>(paths[i]))
                {
                    if (flipVertical)
                        image.Mutate(x => x.Flip(FlipMode.Vertical));
                    if (flipHorizontal)
                        image.Mutate(x => x.Flip(FlipMode.Horizontal));
                    var pixels = new List<byte>(3 * image.Width * image.Height);
                    for (int y = 0; y < image.Height; y++)
                    {
                        var row = image.GetPixelRowSpan(y);
                        for (int x = 0; x < image.Width; x++)
                        {
                            pixels.Add(row[x].R);
                            pixels.Add(row[x].G);
                            pixels.Add(row[x].B);
                            pixels.Add(row[x].A);
                        }
                    }
                    GL.TexImage2D(TextureTarget.TextureCubeMapPositiveX + i, 0, PixelInternalFormat.Rgba, image.Width, image.Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, pixels.ToArray());
                }
            }
            GL.GenerateMipmap(GenerateMipmapTarget.TextureCubeMap);
        }

        /// <summary>
        /// 将对应材质绑定到纹理单元
        /// </summary>
        /// <param name="textureUnit">纹理单元</param>
        public void Use(int textureUnit = 0)
        {
            GL.ActiveTexture(TextureUnit.Texture0 + textureUnit);
            GL.BindTexture(TextureTarget.TextureCubeMap, Handle);
        }
    }
}
